package com.demo.juc.task;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: jxm
 * @Description: 测试 CompletableFuture
 * @Date: 2021/12/27 13:50
 * @Version: 1.0
 */
public class TestFuture {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        System.out.println("main-------------start--------------");
        /**
         * 异步运行 runAsync
         */
//        CompletableFuture.runAsync(()->{
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10/2;
//            System.out.println("运行结果："+i);
//        },executor);

//        System.out.println("main-------------end--------------");

        /**
         * 异步运行，有返回值 supplyAsync
         */
//        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor);
//        //阻塞等结果
//        Integer integer = supplyAsync.get();
//        System.out.println("main-------------end--------------"+integer);

        /**
         * 计算完成时回调  whenComplete 感知异常，无法修改数据 方法成功后的处理
         * 处理异常  exceptionally 感知异常，可以修改默认值
         */
//        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).whenComplete((res,exception)->{
//            System.out.println("异步任务完成....结果是："+res+",异常是："+exception);
//        }).exceptionally((throwable) -> { //处理异常
//            //感知异常，可以修改默认值
//            return 10;
//        });
//        System.out.println("main-------------end--------------"+supplyAsync.get());

        /**
         * 计算完成后的处理（无论是否成功） handle
         */
//        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).handle((res,throwable)->{
//            if(res != null){
//                return res*3;
//            }
//            if(throwable != null){
//                return -1;
//            }
//            return 0;
//        });
//        System.out.println("main-------------end--------------:"+supplyAsync.get());

        /**
         * 线程串行化
         * thenRun 当上一个任务执行完成时执行（不能获取上一步的结果）
         * thenAccept 当上一个任务执行完成时执行(获取上一个任务的执行结果)
         * thenApply 当上一个任务执行完成时执行(获取上一个任务的执行结果,并且有返回值)
         *
         */
//        CompletableFuture<Void> runAsync = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).thenRunAsync(() -> {
//            System.out.println("任务2启动了。。。。。。。。。。。");
//        });
//        System.out.println("main-------------end--------------:");

//        CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).thenAcceptAsync((res) -> {
//            System.out.println("任务2启动了。。。。。。。。。。。,上一不执行结果："+res);
//        },executor);
//        System.out.println("main-------------end--------------:");

//        CompletableFuture<Integer> async = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).thenApplyAsync((res) -> {
//            System.out.println("任务2启动了。。。。。。。。。。。,上一不执行结果：" + res);
//            return res * 3;
//        }, executor);
//        System.out.println("main-------------end--------------:"+async.get());


        /**
         * 两任务组合 ---两个都要完成
         * runAfterBoth 组合两个Future任务 ，不需要获取Future结果
         * thenAcceptBoth 组合两个Future任务,获取两个Future的结果，然后处理，没有返回值
         * thenCombine 组合两个Future任务,获取两个Future的结果,并返回当前任务的返回值
         */

//        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务1线程。。。。。。。。" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("任务1结束.............");
//            return i;
//        }, executor);
//
//        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务2线程。。。。。。。。" + Thread.currentThread().getId());
//            System.out.println("任务2结束.............");
//            return "hello";
//        }, executor);
//
//        future1.runAfterBothAsync(future2,()->{
//            System.out.println("任务3开始了........................");
//        },executor);
//
//        System.out.println("main-------------end--------------:");

//        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务1线程。。。。。。。。" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("任务1结束.............");
//            return i;
//        }, executor);
//
//        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务2线程。。。。。。。。" + Thread.currentThread().getId());
//            System.out.println("任务2结束.............");
//            return "hello";
//        }, executor);
//
//        future1.thenAcceptBothAsync(future2,(f1,f2)->{
//            System.out.println("任务3开始了........................"+f1+"===="+f2);
//        },executor);
//
//        System.out.println("main-------------end--------------:");

//        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务1线程。。。。。。。。" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("任务1结束.............");
//            return i;
//        }, executor);
//
//        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务2线程。。。。。。。。" + Thread.currentThread().getId());
//            System.out.println("任务2结束.............");
//            return "hello";
//        }, executor);
//
//        CompletableFuture<String> async = future1.thenCombineAsync(future2, (f1, f2) -> {
//            System.out.println("任务3开始了........................" + f1 + "====" + f2);
//            return f1 + f2;
//        }, executor);
//
//        System.out.println("main-------------end--------------:"+async.get());


        /**
         * 同上 两任务组合
         * 两任务组合 -----》一个任务完成就执行
         * runAfterEither 两个任务只要有一个任务执行完成，不需要获取结果，处理完成，也没返回值
         * acceptEither 两个任务只要有一个任务执行完成，获取任务返回结果，处理完成，没返回值
         * applyToEither 两个任务只要有一个任务执行完成，获取任务返回结果，处理完成，有返回值
         */

//        CompletableFuture<Object> future1 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务1线程。。。。。。。。" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("任务1结束.............");
//            return i;
//        }, executor);

//        CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务2线程。。。。。。。。" + Thread.currentThread().getId());
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("任务2结束.............");
//            return "hello";
//        }, executor);

//        future1.runAfterEitherAsync(future2, () -> {
//            System.out.println("任务3开始了........................");
//        }, executor);

//        future1.acceptEitherAsync(future2, (res) -> {
//            System.out.println("任务3开始了........................:"+res);
//        }, executor);

//        CompletableFuture<String> apply = future1.applyToEitherAsync(future2, (res) -> {
//            System.out.println("任务3开始了........................:" + res);
//            return res + "   hello";
//        }, executor);

//        System.out.println("main-------------end--------------:"+apply.get());


        /**
         * 多任务组合
         * allOf 等待所有任务完成
         * anyOf 只要有一个任务完成
         */
        CompletableFuture<Object> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询1");
            return "hello1";
        }, executor);

        CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询2");
            return "hello2";
        }, executor);

        CompletableFuture<Object> future3 = CompletableFuture.supplyAsync(() -> {

            try {
                Thread.sleep(3000);
                System.out.println("查询3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello3";
        }, executor);

//        CompletableFuture<Void> all = CompletableFuture.allOf(future1, future2, future3);
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2, future3);
        Object o = anyOf.get();

        System.out.println("main-------------end--------------:"+o);

    }
}
